-- UISkyRelicMain
-- Create by cheny3
-- 掠夺主界面

-- UISkyRelicMain继承自Layer
UISkyRelicMain = class("UISkyRelicMain", function()
    return cc.Layer:create();
end);

-- 最多15个位置
local MAX_POS_NUM = 15;

function UISkyRelicMain.create()
    AudioM.playFx("wear_equip");
    return UISkyRelicMain.new();
end

-- 构造函数
function UISkyRelicMain:ctor()
    -- 初始化
    self:setName("UISkyRelicMain");
    -- 掠夺界面
    local node = cc.CSLoader:createNode("layout/sky_city/SkyRelicMain.csb");
    self:addChild(node);
    self.node = node;

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 重绘
    self:redraw();

    -- 云层的滚动
    self:startCloud();

    -- 适配
    self:resize();
end

-- 适配
function UISkyRelicMain:resize()
    local node = self.node;

    -- bg居中显示并充满整个屏幕
    AlignM.fitToScreen(node, "bg");
    AlignM.fitToScreen(node, "bg2");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
end

-- 重绘界面
function UISkyRelicMain:redraw()
    -- 绘制标题
    local titleNode = findChildByName(self.node, "CT/title_bar");
    local titleLabel = findChildByName(titleNode, "title");
    titleLabel:setString(getLocStr("relic_main_title"));
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 绘制倒计时
    self:redrawTime();

    -- 绘制地图上元素
    self:redrawElement();
end

-- 注册元素的点击事件
function UISkyRelicMain:registerItemClick(node)
    local nodeInfo = node.info;
    local bg = node.bg;
    local icon = node.icon;

    local function onClickBg(sender, eventType)
        if eventType == ccui.TouchEventType.began then
            -- 1.变小
            local downTime  = 0.25/2;
            local scaleDown = cc.ScaleTo:create(downTime, 0.8);
            local scaleDown2 = cc.ScaleTo:create(downTime, 0.8);
            bg:runAction(scaleDown);
            icon:runAction(scaleDown2);
        elseif eventType == ccui.TouchEventType.ended then
            -- 2.变大
            local downTime  = 0.25/2;
            local scaleUp = cc.ScaleTo:create(downTime, 1);
            local scaleUp2 = cc.ScaleTo:create(downTime, 1);
            bg:runAction(scaleUp);
            icon:runAction(scaleUp2);
        elseif eventType == ccui.TouchEventType.canceled then
            -- 3.变大
            local downTime  = 0.25/2;
            local scaleUp = cc.ScaleTo:create(downTime, 1);
            local scaleUp2 = cc.ScaleTo:create(downTime, 1);
            bg:runAction(scaleUp);
            icon:runAction(scaleUp2);
        end

        if eventType == ccui.TouchEventType.ended then
            -- 点击
            if nodeInfo[1] == "relic" or nodeInfo[1] == "boss" then
                -- 打开详细界面
                require "game/ui/form/sky_city/UIRelicUserInfo";
                UIMgr.getCurrentScene():removeFormByName("UIRelicUserInfo");
                local uiForm = UIRelicUserInfo.create(nodeInfo);
                UIMgr.getCurrentScene():addForm(uiForm);
                AudioM.playFx("ui_open1");
            elseif nodeInfo[1] == "eggs" then
                -- 直接领取彩蛋
                SkyRelicM.takeRelicEggsBonus(nodeInfo[2]);
                AudioM.playFx("market_buy_success");
            end
        end
    end
    bg:addTouchEventListener(onClickBg);
    bg:setTouchEnabled(true);
end

-- 设置播放BOSS淡出效果
function UISkyRelicMain:setBossFadeOutEffect(pos, msg)
    self.bossFadePos = pos;
    self.msg = msg;
end

-- 设置需播放淡出的节点
function UISkyRelicMain:setFadeOutEffect(pos, msg)
    self.fadePos = pos;
    self.msg = msg;
end

-- 设置需要播放抖动的节点
function UISkyRelicMain:setFailEffect(pos, msg)
    self.shakePos = pos;
    self.msg = msg;
end

-- 播放更换对手特效
function UISkyRelicMain:playChangeEffect(pos)
    local node = findChildByName(self.node, "CT/map_pos/pos" .. pos);
    node:setVisible(false);
    node:stopAllActions();

    local function delay()
        node:stopAllActions();
        node:setVisible(true);
        if node.oriPos then
            node:setPosition(node.oriPos);
        end

        local function callback()
            -- 位置上下飘移
            node:stopAllActions();
            playFluctuateAnima2(node, 0.7, 5);
        end

        -- 播放效果
        playRelicChangeEffect(node, callback);
    end
    performWithDelay(self, delay, 0.01);
end

-- 节点播放Boss淡出效果
function UISkyRelicMain:playBossFadeOutEffect()
    if not self.bossFadePos then
        return;
    end

    local node = findChildByName(self.node, "CT/map_pos/pos" .. self.bossFadePos);
    node.bg:setTouchEnabled(false);

    -- 爆炸效果，需要在最底层
    local effectNode = cc.Node:create();
    node:addChild(effectNode);
    effectNode:setLocalZOrder(-2);
    -- 两端相互延迟的爆炸效果
    playEffect(effectNode, 1701, -25, 20, nil, 0.3);
    local function delayBoom()
        playEffect(effectNode, 1701, 25, -10, nil, 0.3);
    end
    performWithDelay(self, delayBoom, 0.4);

    -- 第一阶段抖动
    playDoorShakeEffect(node, 0.04, 2, 10, true);

    -- 第二阶段淡出
    local function action3()
        local delay = cc.DelayTime:create(0.3);
        local fadeOut = cc.FadeOut:create(0.8);
        local scaleUp = cc.ScaleTo:create(0.8, 1.8);
        local action1 = cc.Sequence:create(scaleUp);
        local action2 = cc.Sequence:create(delay, scaleUp:clone());
        local fadeOut2 = cc.Sequence:create(delay, fadeOut:clone());
        if node.copyNode then
            node.copyNode:setVisible(true);
            node.copyNode:runAction(action1);
            for _, childNode in pairs(node.copyNode:getChildren()) do
                childNode:runAction(fadeOut:clone());
            end
            node.copyNode:setLocalZOrder(-1);
        end
        node:runAction(action2);
        node:runAction(fadeOut2);
        node.bg:setOpacity(128);
        node.icon:setOpacity(128);
    end
    performWithDelay(self, action3, 2.0);

    -- 移除复制的节点
    local function remove()
        if node.copyNode then
            node.copyNode:setVisible(false);
            node:getParent():removeChild(node.copyNode);
            node.copyNode = nil;
        end
    end
    performWithDelay(self, remove, 3.5);

    if self.msg then
        -- 弹字
        local list = splitString(self.msg, "\n");
        splitAlert(list, 0.6);
    end

    -- 绘制倒计时
    self:redrawTime();

    -- 置空
    self.bossFadePos = nil;
    self.msg = nil;
end

-- 节点播放淡出效果
function UISkyRelicMain:playFadeOutEffect()
    if not self.fadePos then
        return;
    end

    local node = findChildByName(self.node, "CT/map_pos/pos" .. self.fadePos);
    node.bg:setTouchEnabled(false);

    -- 淡出
    local fadeOut = cc.FadeOut:create(0.5);
    local scaleUp = cc.ScaleTo:create(0.1, 1.2);
    local scaleDown = cc.ScaleTo:create(0.3, 0.8);
    node:runAction(cc.Sequence:create(scaleUp, scaleDown));
    node:runAction(fadeOut);

    if self.msg then
        -- 弹字
        local list = splitString(self.msg, "\n");
        splitAlert(list, 0.6);
    end

    -- 绘制倒计时
    self:redrawTime();

    -- 置空
    self.fadePos = nil;
    self.msg = nil;
end

-- 播放抖动效果
function UISkyRelicMain:playFailEffect()
    if not self.shakePos then
        return;
    end

    local node = findChildByName(self.node, "CT/map_pos/pos" .. self.shakePos);
    node.bg:setTouchEnabled(false);

    -- 抖动
    local function delay2()
        playDoorShakeEffect(node, 0.04, 2, 3, true);
    end

    if self.msg then
        local msg = self.msg;
        local function delay()
            -- 弹字
            local list = splitString(msg, "\n");
            splitAlert(list, 0.8);

            for i = 1, #list do
                -- 按照弹字抖动
                performWithDelay(self, delay2, 1.0 * (i - 1));
            end
        end
        performWithDelay(self, delay, 0.8);
    end

    -- 绘制倒计时
    self:redrawTime();

    -- 置空
    self.shakePos = nil;
    self.msg = nil;
    node.bg:setTouchEnabled(true);
end

-- 绘制地图元素
function UISkyRelicMain:redrawElement()
    local needArrange = false;
    local relicElementPos = ME.user.dbase:query("relic_element_pos", {});

    for i = 1, MAX_POS_NUM do
        local info = relicElementPos[i];
        local childNode = findChildByName(self.node, "CT/map_pos/pos" .. i);
        -- 先记录节点的原始位置
        if not childNode.oriPos then
            childNode.oriPos = cc.p(childNode:getPosition());
        end

        if info then
            -- 该位置有信息
            childNode:removeAllChildren();
            childNode:stopAllActions();
            childNode:setVisible(true);
            childNode:setOpacity(255);
            childNode:setScale(1);
            childNode:setPosition(childNode.oriPos);
            childNode:setAnchorPoint(0, 0);

            local function delayPlay()
                -- 位置上下飘移
                playFluctuateAnima2(childNode, 0.7, 5);
            end
            -- 隔开延迟
            performWithDelay(self, delayPlay, math.random(0.1, 0.3));

            local iconPath;
            if info[1] == "boss" then
                iconPath = getRelicIcon(SkyRelicM.queryBoss(info[2], "screen_icon"));
                if not ME.user.dbase:query("relic_boss_info", {})["boss_id"] then
                    -- 没有信息，直接隐藏
                    childNode:setVisible(false);
                    needArrange = true;
                end
            elseif info[1] == "relic" then
                -- 获取玩家的冈布奥
                local m = table.deepcopy(ME.user.dbase:query("relic_rob_list", {}));
                if m[info[2]] then
                    local userInfo = m[info[2]];
                    local pets = userInfo["pets"] or {};
                    table.sort(pets);
                    local randomNum = math.random(math.max(#pets-4, 1), #pets);
                    local petId = pets[randomNum];

                    local oldPetId = SkyRelicM.getShowPetId("relic", info[2]);
                    if oldPetId and table.indexOf(pets, oldPetId) ~= -1 then
                        -- 已经抽取过了，直接使用旧的
                        petId = oldPetId;
                    else
                        -- 记录
                        SkyRelicM.setShowPetId("relic", info[2], petId);
                    end

                    iconPath = getSmallHeroIconPath(PetM.getDefaultIcon(petId));
                else
                    -- 没有信息，直接隐藏
                    childNode:setVisible(false);
                    needArrange = true;
                end
            elseif info[1] == "eggs" then
                iconPath = getRelicIcon(SkyRelicM.queryEggs(info[2], "screen_icon"));
                local eggInfo = ME.user.dbase:query("relic_eggs_info", {});
                local eggList = eggInfo["egg_list"] or {};
                if table.indexOf(eggList, info[2]) == -1 then
                    -- 没有信息，直接隐藏
                    childNode:setVisible(false);
                    needArrange = true;
                end
            end

            -- 图标信息
            local imgBg = ccui.ImageView:create(getRelicTypeBg(info[1]));
            imgBg:setName("relic_node_bg");
            local imgIcon = ccui.ImageView:create(iconPath);
            imgIcon:setTouchEnabled(false);
            imgBg:setTouchEnabled(true);

            childNode:addChild(imgBg);
            childNode:addChild(imgIcon);

            if info[1] == "boss" or info[1] == "relic" then
                -- 遗迹和BOSS复制一个节点用来表现效果
                local copyNode = cc.Node:create();
                copyNode:setPosition(childNode.oriPos);
                childNode:getParent():addChild(copyNode);
                copyNode:addChild(imgBg:clone());
                copyNode:addChild(imgIcon:clone());
                childNode.copyNode = copyNode;
                copyNode:setVisible(false);
            end

            childNode.bg = imgBg;
            childNode.info = info;
            childNode.icon = imgIcon;

            -- 图标上移两个像素
            imgIcon:setPositionY(2);

            -- 注册点击事件
            self:registerItemClick(childNode);
        else
            -- 没有信息，隐藏节点
            childNode:setVisible(false);
        end
    end

    if needArrange then
        -- 需要整理数据
        Operation.cmd_arrange_relic_element_pos();
    end
end

-- 绘制倒计时
function UISkyRelicMain:redrawTime()
    if self.isTick then
        return;
    end

    local subTitleNode = findChildByName(self.node, "CT/sub_title");
    local function tick()
        local leftTime = SkyRelicM.getRelicRefreshLeftTime();
        if leftTime <= 0 then
            subTitleNode:setVisible(false);
            self.isTick = false;

            local nextRefreshTime = ME.user.dbase:query("next_relic_time", MAX_VALUE);
            local curTime = TimeM.getServerTime();
            local leftTime = nextRefreshTime - curTime;
            if leftTime <= 0 then
                -- 倒计时确实小于0，主动请求一次
                Operation.cmd_request_refresh_relic_list();
            end

            return;
        end

        subTitleNode:setVisible(true);

        local timeDesc = self:analysisLeftTime(leftTime);
        -- 拼接文字
        local desc = string.format(getLocStr("relic_refresh_time"), timeDesc);
        TextStyleM.setTextStyle(subTitleNode, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_BROWN_YELLOW);
        subTitleNode:setString(desc);
        performWithDelay(self, tick, 1);
    end
    self.isTick = true;
    tick();
end

-- 倒计时格式
function UISkyRelicMain:analysisLeftTime(leftTime)
    if leftTime > 3600 then
        return math.floor(leftTime/3600) .. "h";
    elseif leftTime > 60 then
        return math.floor(leftTime/60) .. "m";
    end
    return math.floor(leftTime) .. "s";
end

-- 显示/隐藏底部按钮
function UISkyRelicMain:showBottomBtn(visible)
    local BT = findChildByName(self.node, "BT");
    BT:setVisible(visible);
end

-- 注册事件处理回调函数
function UISkyRelicMain:registerEventCallback()
    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(eventType)
        if eventType == "exit" then
            EventMgr.removeAll("UISkyRelicMain");
        elseif eventType == "enter" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY , TOPMENU_FRAME_RUINS_SCRAP, TOPMENU_FRAME_HEAD_AIRSHIP);
            -- 尝试去获取最新的信息
            SkyRelicM.refreshRelicInfos();
        end
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UISkyRelicMain", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UISkyRelicMain" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY , TOPMENU_FRAME_RUINS_SCRAP, TOPMENU_FRAME_HEAD_AIRSHIP);
            self:showBottomBtn(true);
            -- 尝试播放效果
            self:playFadeOutEffect();
            self:playFailEffect();
            self:playBossFadeOutEffect();
        elseif para["lose"] == "UISkyRelicMain" then
            self:showBottomBtn(false);
        end
    end);

    -- 设置战斗信息
    EventMgr.register("UISkyRelicMain", event.RECEIVE_ROB_RESULT, function(para)
        self.battleInfo = para.battleInfo;
    end);

    -- 战斗开始回调
    EventMgr.register("UISkyRelicMain", event.START_SKY_BATTLE, function(para)
        local battle = para["battle"];

        -- 天空战
        require "game/ui/form/sky_city/UISkyCityCombat";
        local UISkyCityCombat = UISkyCityCombat.create(para.battle);
        UIMgr.getCurrentScene():addForm(UISkyCityCombat);

        local battleInfo = self.battleInfo;
        local pos = self.battleInfo[3];

        -- 根据结果设置需要播放的效果
        if battle.result and battle.result == 1 then
            local bonus = battle.bonus;
            local bonusTip = getLineBreakBonusTip(bonus);
            local msg;
            if battleInfo[1] == "relic" then
                msg = getLocStr("relic_rob_win_tip") .. "\n" .. bonusTip;
                self:setFadeOutEffect(pos, msg);
            elseif battleInfo[1] == "boss" then
                local bossName = SkyRelicM.queryBoss(battleInfo[2], "name");
                msg = string.format(getLocStr("relic_boss_win_tip"), bossName) .. "\n" .. bonusTip;
                self:setBossFadeOutEffect(pos, msg);
            end
        else
            -- 重新获取信息
            local data = table.deepcopy(SkyRelicM.getTargetRobInfo(battleInfo[2]));
            local lastTime = data["last_fail"] or 0;
            local robWaitTime = FormulaM.invoke("CALC_ROB_FAIL_WAIT_TIME", data["fail_times"], battleInfo[1] == "boss");
            local leftTime = lastTime + robWaitTime - TimeM.getServerTime();
            -- 显示剩余时间
            local timeStr = remainingTimeDesc(leftTime);
            local msg;
            if battleInfo[1] == "relic" then
                msg = string.format(getLocStr("relic_rob_fail_tip"), timeStr);
            elseif battleInfo[1] == "boss" then
                local bossName = SkyRelicM.queryBoss(battleInfo[2], "name");
                msg = string.format(getLocStr("relic_boss_fail_tip"), bossName);
            end
            self:setFailEffect(pos, msg);
        end
    end);

    -- 获得彩蛋奖励
    EventMgr.register("UISkyRelicMain", event.RELIC_EGG_BONUS, function(para)
        -- 改成直接弹字
        local elementPos = SkyRelicM.getRelicElementPos("eggs", para.id);
        local bonusTip = getLineBreakBonusTip(para.bonus);
        local msg = getLocStr("relic_find_eggs_tip") .. "\n" .. bonusTip;
        self:setFadeOutEffect(elementPos, msg);
        self:playFadeOutEffect();
    end);

    -- 刷新地图
    EventMgr.register("UISkyRelicMain", event.RELIC_REFRESH_MAP, function(para)
        if self.shakePos or self.fadePos or self.bossFadePos then
            -- 有效果要表现，先不刷新
            return;
        end
        self:redraw();
    end);

    -- 掠夺列表更新了，弹出最新信息效果
    EventMgr.register("UISkyRelicMain", event.RELIC_CHANGE_TARGET, function(para)
        local pos = para.pos;
        -- 播放效果
        self:playChangeEffect(pos);
    end);
end

-- 注册点击事件
function UISkyRelicMain:registerTouchEvent()
    -- 注册返回按钮点击事件
    local btnBack = findChildByName(self.node,"BT/btn_back");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_return");
            -- 关闭当前界面
            UIMgr.getCurrentScene():removeFormByName("UISkyRelicMain");
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));

    -- 说明按钮
    local btnBuild = findChildByName(self.node, "BT/btn_desc");
    local function onBuildClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");
            -- 弹出说明界面
            require "game/ui/form/sky_city/UIRelicDesc";
            UIMgr.getCurrentScene():removeFormByName("UIRelicDesc");
            uiForm = UIRelicDesc.create();
            UIMgr.getCurrentScene():addForm(uiForm);
        end
    end
    AddTouchEventListener(btnBuild, onBuildClick);
    TextStyleM.setTextStyle(btnBuild, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBuild:setTitleText(getLocStr("btn_text_help"));
end

-- 开始云层移动效果
function UISkyRelicMain:startCloud()
    -- 移出右边后，在左边飘来（循环不断）
    local speedList = {23, 15, 10};

    local delayList = {25, 32, 50};

    for index = 1, 3 do
        self:cloudMoveEffect(index, delayList[index], speedList[index]);
    end
end

-- 云移动的效果
function UISkyRelicMain:cloudMoveEffect(index, delay, speed)
    local CT = findChildByName(self.node, "CT");
    local cloudNode = findChildByName(CT, "cloud_" .. index);
    local cloudPos = cc.p(cloudNode:getPosition());
    local times = 1;

    local toPos;
    local fromPos;

    local function cloudEffect()
        local icon = ccui.ImageView:create();
        icon:loadTexture(getSkyCityRuinsIconPath(string.format("cloud_%d", index)));
        icon:setAnchorPoint(0.5, 0.5);

        if times == 1  then
            fromPos = cc.p(- math.random(20), 0);
            icon:setPosition(fromPos);
        elseif times == 2 then
            fromPos = cc.p(cloudPos.x - 560, 0);
            icon:setPosition(fromPos);
        else
            fromPos = cc.p(cloudPos.x - 640, 0);
            icon:setPosition(fromPos);
        end

        toPos = cc.p(cloudPos.x + 640, 0);
        local duration = cc.pGetDistance(fromPos, toPos) / speed;

        local moveTo = cc.MoveTo:create(duration, toPos);

        local callfunc = cc.CallFunc:create(function()
            cloudNode:removeChild(icon);
        end);

        icon:runAction(cc.Sequence:create(moveTo, callfunc));

        cloudNode:addChild(icon);

        local finalDelay = 1;
        if times > 1  then
            finalDelay = delay;
        end

        times = times + 1;

        performWithDelay(cloudNode, cloudEffect, finalDelay);
    end

    cloudEffect();
end